<template>
  <div style="padding-top: 50px">
    <a-row justify="center">
      <a-col :xs="22" :md="22" :lg="22" :xl="22" :xxl="17">
        <div style="text-align: center;font-size: 3em"><span>题目录入</span></div>
      </a-col>
      <a-col :xs="22" :md="22" :lg="22" :xl="22" :xxl="17">
        <div style="min-height: 140px">
          <h2>基础信息:</h2>
          <a-form ref="problemPad" @finish="submitQus" :model="question" :label-col="{ span: 2 }" :wrapper-col="{ span: 16 }">
            <a-form-item label="题目来源:" name="type">
              <a-select v-model:value="question.type" :options="typeOptions" style="width: 120px" @blur="queryExistOnChange"></a-select>
            </a-form-item>
            <a-form-item label="年份:" name="year">
              <a-select v-model:value="question.year" style="width: 120px" :options="yearOptions" @blur="queryExistOnChange">
              </a-select>
            </a-form-item>
            <a-form-item label="题号:" name="number">
              <a-input-number v-model:value="question.number" @blur="queryExistOnChange" style="width: 120px" :min="1" :max="60"></a-input-number>
            </a-form-item>
            <a-form-item label="学科:" name="subject">
              <a-select v-model:value="question.subject" :options="subjectOptions" @change="changeTagsOptionBySubject" style="width: 120px"/>
            </a-form-item>
            <a-form-item label="答案选项:" name="choice">
              <a-select v-model:value="question.choice" :options="choiceOptions" style="width: 120px"/>
            </a-form-item>
            <a-form-item label="知识点:" name="topTag">
              <a-select v-model:value="topTag" :fieldNames="{ label: 'name', value: 'name' }" :options="tagsOptions" style="width: 400px"/>
            </a-form-item>
            <a-form-item label="标签:" name="tags">
              <a-select v-model:value="question.tags" mode="tags" style="width: 400px"/>
            </a-form-item>
            <a-form-item :wrapper-col="{ offset: 2, span: 16 }">
              <a-button type="primary" html-type="submit">提交</a-button>
              <a-button type="primary" style="margin-left: 25px" @click="queryQus">搜索</a-button>
              <a-button type="primary" style="margin-left: 25px" @click="resetQus">重置</a-button>
            </a-form-item>
          </a-form>
        </div>
        <div style="margin-top: 30px">
          <h2>题干:</h2>
          <VueEditor :modelValue="qusContent" placeholder="在这里写入题干" ref="VEditorQus"/>
        </div>
        <div style="margin-top: 40px">
          <h2>答案:</h2>
          <VueEditor :modelValue="ansContent" placeholder="在这里写入答案" ref="VEditorAns"/>
        </div>
      </a-col>
    </a-row>
    <div style="height: 30px"></div>
    <div class="footer">
      <span style="font-family:arial,serif;">Copyright &copy; 2022 Just for fun.</span>
    </div>
  </div>
</template>

<script lang="ts">
import { defineComponent, ref, reactive, onMounted } from 'vue'
import { Form, Row, Col, InputNumber, Button, message, Select } from 'ant-design-vue'
import type { FormInstance } from 'ant-design-vue'
import VueEditor from '@/components/VueVditor.vue'
import { getQesByYearNumber, getSubjectCate, upload408Question, existQus } from '@/service'
import { transUrl } from '@/utils/ds'
import { SUBJECT_CATE_KEY } from '@/utils/constants'

interface Option {
  name: string,
  id: string
}

interface SubjectCateOption {
  CS: Option[],
  OS: Option[],
  CCP: Option[],
  NET: Option[]
}

interface Question {
  id: number,
  year: string,
  number: number,
  question: string,
  tags: string[],
  type: string,
  subject: string,
  choice: string
}

interface Answer {
  id: number,
  answer: string
}

export default defineComponent({
  name: 'AddQus',
  components: {
    VueEditor,
    AForm: Form,
    ARow: Row,
    ACol: Col,
    AFormItem: Form.Item,
    AButton: Button,
    ASelect: Select,
    AInputNumber: InputNumber
  },
  setup () {
    const question = reactive<Question>({
      id: 0,
      year: '',
      number: 1,
      question: '',
      tags: [],
      type: '408',
      subject: '',
      choice: ''
    })
    const topTag = ref<string>('')
    const answer = reactive<Answer>({
      id: 0,
      answer: ''
    })
    const qusContent = ref<string>('###### 题干')
    const ansContent = ref<string>('')
    const problemPad = ref<FormInstance>()
    const VEditorQus = ref<InstanceType<typeof VueEditor> | null>()
    const VEditorAns = ref<InstanceType<typeof VueEditor> | null>()
    const choiceOptions = reactive([
      { label: 'A', value: 'A' },
      { label: 'B', value: 'B' },
      { label: 'C', value: 'C' },
      { label: 'D', value: 'D' }
    ])
    const typeOptions = reactive([
      { label: '408', value: '408' },
      { label: '803', value: '803' },
      { label: '其他', value: '0' }
    ])
    const yearOptions = reactive<{ label: string, value: string }[]>([])
    const subjectOptions = reactive([
      { label: '数据结构', value: 'CS' },
      { label: '组成原理', value: 'CCP' },
      { label: '操作系统', value: 'OS' },
      { label: '计算机网络', value: 'NET' }
    ])

    const subjectCate = ref<SubjectCateOption>({
      CS: [],
      OS: [],
      CCP: [],
      NET: []
    })

    const tagsOptions = ref<Option[]>([])

    const setupYearOption = () => {
      const today = new Date()
      const year = today.getFullYear()
      for (let i = year - 1; i >= 2009; i--) {
        yearOptions.push({ label: i.toString(), value: i.toString() })
      }
    }

    const changeTagsOptionBySubject = (value:string) => {
      if (value === 'CS') {
        tagsOptions.value = subjectCate.value.CS
      } else if (value === 'OS') {
        tagsOptions.value = subjectCate.value.OS
      } else if (value === 'CCP') {
        tagsOptions.value = subjectCate.value.CCP
      } else if (value === 'NET') {
        tagsOptions.value = subjectCate.value.NET
      } else {
        tagsOptions.value = []
      }
      topTag.value = ''
    }

    const getQusTxt = () => {
      const txt = VEditorQus.value?.getEditorValue()
      return txt === undefined ? '' : txt
    }

    const getAnsTxt = () => {
      const txt = VEditorAns.value?.getEditorValue()
      return txt === undefined ? '' : txt
    }

    const setQusTxt = (value: string) => {
      VEditorQus.value?.setEditorValue(value)
    }

    const setAnsTxt = (value: string) => {
      VEditorAns.value?.setEditorValue(value)
    }

    const validQuestion = (): boolean => {
      if (question.type === '') {
        message.info('请设置题目来源')
        return false
      }
      if (question.type !== '0') {
        if (question.year === '') {
          message.info('请设置题目年份')
          return false
        }

        if (question.number <= 0 || question.number > 60) {
          message.info('题号的范围在 0~60，请检查')
          return false
        }
      }

      if (question.subject === '') {
        message.info('请设置学科')
        return false
      }

      if (question.choice === '') {
        message.info('请设置答案')
        return false
      }

      if (topTag.value === '') {
        message.info('请设置题目所属知识点')
        return false
      }

      if (question.question === '') {
        message.info('请设置题目')
        return false
      }
      return true
    }

    const submitQus = () => {
      const qus = question
      const ans = answer
      ans.answer = getAnsTxt()
      qus.question = getQusTxt()
      if (!validQuestion()) {
        return
      }
      const tags = topTag.value + '#' + qus.tags.join('#')
      const submitData = {
        question: {
          id: qus.id,
          year: qus.year,
          number: qus.number,
          question: qus.question,
          tag: tags,
          type: qus.type,
          subject: qus.subject,
          choice: qus.choice
        },
        answer: {
          id: ans.id,
          answer: ans.answer
        }
      }
      upload408Question(submitData)
        .then((response) => {
          if (response.status !== 200) {
            return
          }
          const resp = response.data
          if (resp.code === 101) {
            message.info('身份失效 请登录')
            return
          }
          if (resp.code !== 0) {
            if (resp.code === 503) {
              message.warn('该题目已经存在 请先检索再提交答案', 1)
              return
            }
            message.error(resp.msg)
            return
          }
          const data = resp.data
          question.id = data.pid
          answer.id = data.aid
          message.info('提交题目成功')
        })
        .catch((err) => {
          console.log(err)
        })
    }

    const queryQus = () => {
      const data:Map<string, string | number> = new Map()
      data.set('year', question.year)
      data.set('number', question.number)
      data.set('type', question.type)
      getQesByYearNumber(data)
        .then((response) => {
          // console.log(response)
          if (response.status !== 200) {
            message.error('请求出错')
            return
          }
          const resp = response.data
          if (resp.code !== 0) {
            message.error(resp.msg)
            return
          }
          const data = resp.data
          // console.log(data)
          if (data === null || data.question === null || data.question === undefined) {
            message.error('未找到记录')
            return
          }
          resetQuestion()
          resetAnswer()
          const qus = data.question
          const ans = data.answer
          // 恢复问题数据
          question.id = qus.id
          question.year = qus.year
          question.number = qus.number
          question.question = transUrl(qus.question)
          question.choice = qus.choice
          question.type = qus.type
          question.subject = qus.subject
          const tags = qus.tag as string
          const ts = tags.split('#')
          if (ts.length > 0) {
            topTag.value = ts[0]
            question.tags = ts.slice(1)
          }
          // 恢复答案数据
          if (ans !== null && ans !== undefined) {
            answer.id = ans.id
            answer.answer = transUrl(ans.answer)
          }
          setQusTxt(question.question)
          setAnsTxt(answer.answer)
        })
        .catch((err) => {
          console.log(err)
        })
    }

    const resetQuestion = () => {
      question.id = 0
      question.year = ''
      question.number = 0
      question.question = ''
      question.subject = ''
      question.type = '408'
      question.tags = []
      question.choice = ''
      topTag.value = ''
    }

    const resetAnswer = () => {
      answer.id = 0
      answer.answer = ''
    }

    const resetQus = () => {
      setQusTxt('###### 题干')
      setAnsTxt('')
      const preType = question.type
      const preYear = question.year
      const pID = question.number + 1
      resetQuestion()
      resetAnswer()
      if (question.type === '0') {
        return
      }
      if (preYear === '') {
        return
      }
      question.year = preYear
      question.number = pID
      question.type = preType
      if (pID >= 1 && pID <= 11) {
        question.subject = 'CS'
        changeTagsOptionBySubject('CS')
      } else if (pID >= 12 && pID <= 22) {
        question.subject = 'CCP'
        changeTagsOptionBySubject('CCP')
      } else if (pID >= 23 && pID <= 32) {
        question.subject = 'OS'
        changeTagsOptionBySubject('OS')
      } else if (pID >= 33 && pID <= 40) {
        question.subject = 'NET'
        changeTagsOptionBySubject('NET')
      }
    }

    const setUpCateOptions = () => {
      const cate = sessionStorage.getItem(SUBJECT_CATE_KEY)
      if (cate !== null) {
        subjectCate.value = JSON.parse(cate)
        return
      }
      getSubjectCate()
        .then((response) => {
          if (response.status !== 200) {
            message.error('请求学科类别出错')
          }
          const resp = response.data
          const data = resp.data
          if (data === null) {
            return
          }
          const cs = data.CS
          const os = data.OS
          const ccp = data.CCP
          const net = data.NET
          cs.forEach((v: string) => {
            if (v === 'acc' || v === 'num') {
              return
            }
            subjectCate.value.CS.push({ name: v, id: `CS_${v}` })
          })

          os.forEach((v: string) => {
            if (v === 'acc' || v === 'num') {
              return
            }
            subjectCate.value.OS.push({ name: v, id: `OS_${v}` })
          })

          ccp.forEach((v: string) => {
            if (v === 'acc' || v === 'num') {
              return
            }
            subjectCate.value.CCP.push({ name: v, id: `CCP_${v}` })
          })

          net.forEach((v: string) => {
            if (v === 'acc' || v === 'num') {
              return
            }
            subjectCate.value.NET.push({ name: v, id: `NET_${v}` })
          })

          sessionStorage.setItem(SUBJECT_CATE_KEY, JSON.stringify(subjectCate.value))
        })
        .catch(() => {
          message.error('请求失败')
        })
    }

    const queryExistOnChange = () => {
      if (question.type === '0') {
        question.number = 0
        question.year = ''
        return
      }
      if (question.year !== '' && question.number > 0 && question.type !== '') {
        existQus(question.type, question.year, question.number)
          .then((response) => {
            if (response.status === 200) {
              const resp = response.data
              if (resp.code === 0 && resp.data === true) {
                message.warn(`${question.type}-${question.year}-${question.number} 已经存在，请先点击搜索，再添加答案`)
              }
            }
          })
      }
    }

    onMounted(() => {
      setupYearOption()
      setUpCateOptions()
    })

    return {
      topTag,
      typeOptions,
      choiceOptions,
      yearOptions,
      subjectOptions,
      tagsOptions,
      question,
      qusContent,
      ansContent,
      problemPad,
      VEditorQus,
      VEditorAns,
      changeTagsOptionBySubject,
      submitQus,
      queryQus,
      resetQus,
      queryExistOnChange
    }
  }
})
</script>

<style scoped>
.footer {
  text-align: center;
  margin-top: 10px;
  margin-bottom: 5px;
  padding: 5px;
}
.footer span {
  display: inline-block;
  font-weight: 400;
}
</style>
